局域网内IP地址冲突检测-version1

计算机网络的课程设计,编写一个程序,或利用某些程序,检测局域网内的IP地址冲突,现将思路整理如下:
分两种情况,一个是,自己是IP地址的冲突者,也就是有人跟自己的IP地址一样。另一个是,自己不是IP地址的冲突者,但是局域网内有IP地址的冲突。

  1. 自己是IP地址的冲突者,向局域网内发送arp报文,内容是自己的IP地址,请求IP地址对应的Mac地址,如果返回了Mac地址,和自己的Mac地址不一样,那么就存在IP地址冲突,而且自己是冲突的一方。
  2. 自己不是IP地址的冲突者,利用scapy的arp函数,发送arp报文,获得局域网内所有IP,以及对应的Mac地址,当然,这个arp请求必须发送多次,如果只发送一次的话,那么可能只有一个相同IP的主机返回了,无法判断冲突,可以在较短时间内多次发送(不可能每次都是相同IP的同一个主机返回),如果这个时间段内,同一个IP地址对应多个Mac地址,那么存在IP地址冲突。

现在将现在完成的部分记录一下。
首先,查看自己的手机的IP地址:

可以看到,手机的IP地址是192.168.1.4
然后,将Win7的IP地址改成上面的IP地址

这时候,在另外一台系统为Ubuntu14.04的电脑上运行程序,检测局域网内的IP地址冲突。
Python代码如下(arp包用的是广播发送,目的Mac地址为全F):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from scapy.all import srp,Ether,ARP,conf
import time

ipscan='192.168.1.6/24'

def ip_conflict():
start = time.clock()
print "start time", start
d = dict()
while True:
end = time.clock()
print "endtime",end
# print "??:"
# print int(end-start)
if int(end-start) > 1:
print ('Timeout!!!')
break

try:
ans,unans=srp(Ether(dst="FF:FF:FF:FF:FF:FF")/ARP(pdst=ipscan),timeout=2,verbose=False)
except Exception,e:
print str(e)
else:
print (" MAC -- IP ")
for snd,rcv in ans:
list_mac=rcv.sprintf("%Ether.src% -- %ARP.psrc%")
mac = rcv.sprintf("%Ether.src%")
ip = rcv.sprintf("%ARP.psrc%")
if ip not in d:
d[ip] = mac
else:
if mac != d[ip]:
print "存在ip地址冲突:",mac,d[ip]
print list_mac
print d

ip_conflict()
print "byebye"

可以看到运行结果,发生了地址冲突:

其中的74:e5:0b:d5:5c:e4正是修改了IP地址的Win7主机


####2015.4.7日更新

为了检测与自己ip冲突的情况,修改了一下源程序,将自己的ip地址加入到字典中了,如果存在IP地址冲突,就提示有IP与自己冲突,程序代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from scapy.all import srp,Ether,ARP,conf,get_if_hwaddr,get_if_addr
import time

ipscan='192.168.1.1/24'

import socket
import fcntl
import struct


def ip_conflict():
start = time.clock()
print "start time", start
d = dict()
ip_me = get_if_addr('wlan0')
mac_me = get_if_hwaddr('wlan0')
d[ip_me] = mac_me
while True:
end = time.clock()
# print "endtime",end
# print "??:"
# print int(end-start)
if int(end-start) > 2:
print ('Timeout!!!')
break

try:
ans,unans=srp(Ether(dst="FF:FF:FF:FF:FF:FF")/ARP(pdst=ipscan),timeout=2,verbose=False)
except Exception,e:
print str(e)
else:
print (" MAC -- IP ")
for snd,rcv in ans:
list_mac=rcv.sprintf("%Ether.src% -- %ARP.psrc%")
mac = rcv.sprintf("%Ether.src%")
ip = rcv.sprintf("%ARP.psrc%")
if ip not in d:
d[ip] = mac
else:
if mac != d[ip]:
print "**************存在ip地址冲突*************"
if ip == ip_me:
print "IP地址为:",ip
print "与本机的ip地址冲突"
print "冲突的mac地址",mac_me,d[ip]
else:
print ""
print "IP地址为:",ip
print "冲突的mac地址为",mac,d[ip]
print "*****************************************"
print list_mac
print d

ip_conflict()
# print get_if_hwaddr('wlan0')
# print get_if_addr('wlan0')
print "byebye"
```

实验环境仍然是上述环境,但是这次Ubuntu的ip是192.168.1.5
现在的问题是,发送的arp报文不会回应,我不知道是不是arp协议本身的原因,于是我用arping命令试了一下,将win7改成Ubuntu1404的ip后,用

$ arping 192.168.1.5
```

命令后,我用wireshark抓包,发现报文发出去了,也收到了回应:

可以看到回应的冲突:duplicate user of 192.168.1.5,也可以看到Win7的mac地址,也就是说是可以收到arp报文回应的。